﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Interscape.TwilioClient;
using Interscape.TwilioClient.Components;
using System.Xml.Serialization;
using System.IO;
using System.ServiceModel.Description;
using System.Configuration;

namespace Interscape.TwilioConsole
{
    class Program
    {

        #region Private Members

        static AccountManager _acctMgr;
        static CallManager _callMgr;
        static IncomingPhoneNumberManager _ipnMgr;
        static NotificationManager _notificationMgr;
        static OutgoingCallerIdManager _callerIdMgr;
        static RecordingManager _recMgr;

        static string _accountSid = ConfigurationManager.AppSettings["AccountSid"];
        static string _apiKey = ConfigurationManager.AppSettings["ApiKey"];

        #endregion

        static void Main(string[] args)
        {
            Console.ForegroundColor = ConsoleColor.Red;
            Console.WriteLine("Welcome to TwilioConsole, a TwilioApi sample by Interscape Technologies!");
            Console.ForegroundColor = ConsoleColor.White;
            Console.WriteLine("Please enter a command: ");

            string command = Console.ReadLine();

            while (!command.Equals("q"))
            {
                try
                {
                    switch (command)
                    {
                        case "show account":
                            // retrieve current account information
                            CheckAccountManager();
                            PrintObject(_acctMgr.Get(), typeof(Account));
                            break;
                        case "edit account":
                            // retrieve individual account record
                            // prompt for the FriendlyName (the only value that can be edited on Accounts)
                            Console.WriteLine("\nPlease enter the desired FriendlyName for this Account:");
                            string friendlyName = Console.ReadLine();
                            
                            //Get the Account, update it, and submit it
                            CheckAccountManager();
                            Account acct = _acctMgr.Get();
                            acct.FriendlyName = friendlyName;
                            PrintObject(_acctMgr.Update(acct), typeof(Account));
                            break;

                        case "show calls":
                            // retrieve record of all completed calls
                            CheckCallManager();
                            PrintObject(_callMgr.GetAll(), typeof(PhoneCallList));
                            break;
                        case "show call":
                            // retrieve current account information
                            Console.WriteLine("\nPlease enter the Sid for the Call to retrieve:");
                            string callSid = Console.ReadLine();
                            CheckCallManager();
                            PrintObject(_callMgr.Get(callSid), typeof(PhoneCall));
                            break;
                        case "place call":
                            // retrieve current account information
                            Console.WriteLine("\nPlease enter the PhoneNumber to call:");
                            string called = Console.ReadLine();
                            Console.WriteLine("\nPlease enter the pre-validated OutgoingCallerID:");
                            string caller = Console.ReadLine();
                            Console.WriteLine("\nPlease enter the Url to post to once the call starts:");
                            string callUrl = Console.ReadLine();

                            PhoneCall call = new PhoneCall();
                            call.Caller = caller;
                            call.Called = called;
                            call.PostArguments.Add("Url", callUrl);
                            //This is required for my test server. Comment out if not necessary.
                            call.PostArguments.Add("Method", "GET");

                            CheckCallManager();
                            PrintObject(_callMgr.PlaceCall(call), typeof(PhoneCall));
                            break;

                        case "show incomingnumbers":
                            // retrieve a list of all IncomingPhoneNumbers
                            CheckIncomingPhoneNumberManager();
                            PrintObject(_ipnMgr.GetAll(), typeof(IncomingPhoneNumberList));
                            break;
                        case "show incomingnumber":
                            // prompt for the FriendlyName (the only value that can be edited on Accounts)
                            Console.WriteLine("\nPlease enter the Sid for the IncomingPhoneNumber to retrieve:");
                            string ipnSid = Console.ReadLine();
                            // prompt for the FriendlyName (the only value that can be edited on Accounts)
                            CheckIncomingPhoneNumberManager();
                            PrintObject(_ipnMgr.Get(ipnSid), typeof(IncomingPhoneNumber));
                            break;
                        case "add local incomingnumber":
                            // prompt for the FriendlyName (the only value that can be edited on Accounts)
                            Console.ForegroundColor = ConsoleColor.Red;
                            Console.WriteLine("\nWARNING: There is NO test mode for this API call.");
                            Console.WriteLine("\nYour Twilio account will be charged $5 if it completes sucessfully.");
                            Console.WriteLine("\nEnter \"cancel\" at the prompt to abort this request.");
                            Console.ForegroundColor = ConsoleColor.White;
                            Console.WriteLine("\nPlease enter the Area Code for the IncomingPhoneNumber you are requesting:");
                            string areaCode = Console.ReadLine();

                            if (areaCode.Trim() != "cancel")
                            {
                                IncomingPhoneNumber ipn = new IncomingPhoneNumber();
                                ipn.Url = "http://demo.twilio.com";
                                ipn.Method = "POST";
                                ipn.FriendlyName = "Test Number";
                                ipn.PostArguments.Add("AreaCode", areaCode);
                                CheckIncomingPhoneNumberManager();
                                PrintObject(_ipnMgr.AddLocal(ipn), typeof(IncomingPhoneNumber));
                            }
                            break;
                        case "add tollfree incomingnumber":
                            // prompt for the FriendlyName (the only value that can be edited on Accounts)
                            Console.ForegroundColor = ConsoleColor.Red;
                            Console.WriteLine("\nWARNING: There is NO test mode for this API call.");
                            Console.WriteLine("\nYour Twilio account will be charged $5 if it completes sucessfully.");
                            Console.WriteLine("\nEnter \"cancel\" at the prompt to abort this request.");
                            Console.ForegroundColor = ConsoleColor.White;
                            Console.WriteLine("\nPlease enter the Area Code for the IncomingPhoneNumber you are requesting:");
                            string areaCode2 = Console.ReadLine();
                            
                            if (areaCode2.Trim() != "cancel")
                            {
                                IncomingPhoneNumber ipn2 = new IncomingPhoneNumber();
                                ipn2.Url = "http://demo.twilio.com";
                                ipn2.FriendlyName = "Test Number";
                                ipn2.PostArguments.Add("AreaCode", areaCode2);
                                CheckIncomingPhoneNumberManager();
                                PrintObject(_ipnMgr.AddTollFree(ipn2), typeof(IncomingPhoneNumber));
                            }
                            break;

                        case "show callerids":
                            //
                            CheckOutgoingCallerIdManager();
                            PrintObject(_callerIdMgr.GetAll(), typeof(OutgoingCallerIdList));
                            break;
                        case "show callerid":
                            //
                            Console.WriteLine("\nPlease enter the Sid for the OutgoingCallerId to retrieve:");
                            string callerId = Console.ReadLine();
                            CheckOutgoingCallerIdManager();
                            PrintObject(_callerIdMgr.Get(callerId), typeof(OutgoingCallerId));
                            break;
                        case "edit callerid":
                            // retrieve individual OutgoingCallerId record
                            // prompt for the FriendlyName (the only value that can be edited on Accounts)
                            Console.WriteLine("\nPlease enter the Sid for the OutgoingCallerId to retrieve:");
                            string cidSid = Console.ReadLine();
                            Console.WriteLine("\nPlease enter the desired FriendlyName for this OutgoingCallerId:");
                            string cidFriendlyName = Console.ReadLine();

                            //Update the OutgoingCallerId
                            //NOTE: The existing OutgoingCallerId instance is not required.
                            CheckOutgoingCallerIdManager();
                            OutgoingCallerId cid = new OutgoingCallerId(cidSid, cidFriendlyName);
                            PrintObject(_callerIdMgr.Update(cid), typeof(OutgoingCallerId));
                            break;

                        case "show notifications":
                            // retrieve current account information
                            CheckNotificationManager();
                            PrintObject(_notificationMgr.GetAll(), typeof(NotificationList));
                            break;
                    }
                }
                catch (TwilioClientException ex)
                {
                    Console.ForegroundColor = ConsoleColor.Red;
                    PrintObject(ex.RestException, typeof(TwilioRestError));
                    Console.ForegroundColor = ConsoleColor.White;
                }

                catch (Exception e)
                {
                    Console.ForegroundColor = ConsoleColor.Red;
                    Console.WriteLine(e.Message);
                    Console.ForegroundColor = ConsoleColor.White;
                }

                Console.WriteLine("\nPlease enter a command: ");
                command = Console.ReadLine();
            }

        }

        #region Utility Methods

        static void CheckAccountManager()
        {
            if (_acctMgr == null)
            {
                _acctMgr = new AccountManager(_accountSid, _apiKey);
            }
        }

        static void CheckCallManager()
        {
            if (_callMgr == null)
            {
                _callMgr = new CallManager(_accountSid, _apiKey);
            }
        }

        static void CheckOutgoingCallerIdManager()
        {
            if (_callerIdMgr == null)
            {
                _callerIdMgr = new OutgoingCallerIdManager(_accountSid, _apiKey);
            }
        }

        static void CheckIncomingPhoneNumberManager()
        {
            if (_ipnMgr == null)
            {
                _ipnMgr = new IncomingPhoneNumberManager(_accountSid, _apiKey);
            }
        }

        static void CheckNotificationManager()
        {
            if (_notificationMgr == null)
            {
                _notificationMgr = new NotificationManager(_accountSid, _apiKey);
            }
        }

        static void PrintObject(Object o, Type type)
        {
            XmlSerializer serializer = new XmlSerializer(type);
            serializer.Serialize(Console.Out, o);
        }

        #endregion

    }
}
